use std::env;

use actix_web::{
    get, middleware, post, web, App, Error, HttpRequest, HttpResponse, HttpServer, Responder,
};
use actix_web_actors::ws;
use dotenv::dotenv;

mod server;
use self::server::MyWebSocket;

struct AppState {
    app_name: String,
}

#[get("/tag")]
async fn tag() -> impl Responder {
    HttpResponse::Ok().body("n-visual")
}

/// WebSocket 握手并启动 `MyWebSocket` actor.
async fn echo_ws(
    req: HttpRequest,
    stream: web::Payload,
    redis: web::Data<redis::Client>,
) -> Result<HttpResponse, Error> {
    let r_tag = req.query_string().to_string();
    if "".eq(&r_tag) {
        // Ok(HttpResponse::Ok().body("缺少必要参数[tag]"))
        Ok(HttpResponse::Ok()
            .content_type("text/plain")
            .body("缺少必要参数[tag]"))
    } else {
        let r_tag_arr: Vec<&str> = r_tag.split("=").collect();
        let r_val = r_tag_arr[1].to_string();
        print!("{}", r_val);
        ws::start(MyWebSocket::new(r_val, redis), &req, stream)
    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    dotenv().ok();

    env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));

    let ws_path = env::var("WS_PATH").unwrap();
    let rs_url = env::var("RS_URL").unwrap();
    let server_port: u16 = env::var("SERVER_PORT").unwrap().parse::<u16>().unwrap();

    let redis = redis::Client::open(rs_url).unwrap();

    log::info!("starting HTTP server at http://0.0.0.0:{server_port}");

    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(redis.clone()))
            .app_data(web::Data::new(AppState {
                app_name: String::from("n-visual"),
            }))
            .service(web::resource(&ws_path).route(web::get().to(echo_ws)))
            .wrap(middleware::Logger::default())
    })
    .workers(2)
    .bind(("0.0.0.0", server_port))?
    .run()
    .await
}
